package org.gnu.williamjoy.marycircles.control;

import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;

import org.gnu.williamjoy.marycircles.R;
import org.gnu.williamjoy.marycircles.view.CirclesDrawView;

import android.content.Context;
import android.graphics.Color;
import android.media.AudioManager;
import android.media.SoundPool;
import android.widget.Toast;

public class GameState {

    private int level;
    private int updateInterval;
    private List<GameRecord> records;
    private long startTimestamp;
    private long lastTimestamp;
    private int background = Color.BLACK;

    private CirclesDrawView view;
    private Context mContext;

    public GameState() {
        records = new LinkedList<GameRecord>();
    }

    public void start() {
        startTimestamp = System.currentTimeMillis();
        lastTimestamp = startTimestamp;
    }

    public GameRecord getLastRecord() {

        return records.get(records.size() - 1);
    }

    public List<GameRecord> getRecords() {
        return records;
    }

    public int getMinRadius() {
        return (int) (1.0f / (Math.sqrt(level) / 256 + 1.0f / 32)) + 1;
    }

    public int getMaxRadius() {
        return (int) (1.0f / (Math.sqrt(level) / 256 + 1.0f / 64)) + 1;
    }

    public int getLevel() {
        return level;
    }

    public void levelUp(int mary_hits, int william_hits) {
        long now = System.currentTimeMillis();
        this.records.add(new GameRecord(mary_hits, william_hits, now
                - lastTimestamp));
        lastTimestamp = now;
        this.background = (int) (Math.random() * Color.LTGRAY + Color.BLACK);
        this.level++;
        toastLevel();
        this.playSound(R.raw.drip);
    }

    public int getUpdateInterval() {
        return updateInterval;
    }

    public void setUpdateInterval(int updateInterval) {
        this.updateInterval = updateInterval;
    }

    public int getMaxCircles() {
        return 2 + level;
    }

    public int getLevelColor() {
        return background;
    }

    public CirclesDrawView getView() {
        return view;
    }

    public void setView(CirclesDrawView view) {
        this.view = view;
        this.mContext = view.getContext();
    }

    public void toastLevel() {
        view.post(new Runnable() {
            public void run() {
                CharSequence text = "Wow! Level Up! [" + level
                        + "], Level Time:"
                        + GameState.this.getLastRecord().getTime() + "ms";
                int duration = Toast.LENGTH_SHORT;

                Toast toast = Toast.makeText(mContext, text, duration);
                toast.show();
            }
        });
    }

    private SoundPool soundPool;
    private HashMap<Integer, Integer> soundPoolMap;

    public void initSounds() {
        soundPool = new SoundPool(4, AudioManager.STREAM_MUSIC, 100);
        soundPoolMap = new HashMap<Integer, Integer>();
        soundPoolMap.put(R.raw.drip,
                soundPool.load(view.getContext(), R.raw.drip, 1));
        soundPoolMap.put(R.raw.hit,
                soundPool.load(view.getContext(), R.raw.hit, 1));
    }

    public void playSound(int sound) {

        AudioManager audioManger = (AudioManager) view.getContext()
                .getSystemService(Context.AUDIO_SERVICE);
        float currentVolume = audioManger
                .getStreamVolume(AudioManager.STREAM_MUSIC);
        float maxVolume = audioManger
                .getStreamMaxVolume(AudioManager.STREAM_MUSIC);
        float volume = currentVolume / maxVolume;

        soundPool.play(soundPoolMap.get(sound), volume, volume, 1, 0, 1f);
    }

    public class GameRecord {
        /*
         * yeah,hard coded, not like this? hmmm..
         */
        private int mary_hits;
        private int william_hists;
        private long time;

        public GameRecord(int mary_hits, int william_hists, long time) {
            this.time = time;
            this.mary_hits = mary_hits;
            this.william_hists = william_hists;
        }

        public int getMary_hits() {
            return mary_hits;
        }

        public void setMary_hits(int mary_hits) {
            this.mary_hits = mary_hits;
        }

        public int getWilliam_hists() {
            return william_hists;
        }

        public void setWilliam_hists(int william_hists) {
            this.william_hists = william_hists;
        }

        public long getTime() {
            return time;
        }

        public void setTime(long time) {
            this.time = time;
        }

        @Override
        public String toString() {
            return "GameRecord [mary_hits=" + mary_hits + ", william_hists="
                    + william_hists + ", time=" + time + "]";
        }

    }
}
